using System.Text;
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using RAGApp.Api.Configurations;
using RAGApp.Api.Data;
using RAGApp.Api.Models;
using RAGApp.Api.Models.DTOs;
using RAGApp.Api.Services.Interfaces;
using Pgvector;
using System.Security.Cryptography;
using Pgvector.EntityFrameworkCore;

namespace RAGApp.Api.Services;

public class XunfeiChatService : IChatService
{
    private readonly ApplicationDbContext _context;
    private readonly XunfeiConfig _config;
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IEmbeddingService _embeddingService;
    private readonly ILogger<XunfeiChatService> _logger;

    public XunfeiChatService(
        ApplicationDbContext context,
        IOptions<XunfeiConfig> config,
        IHttpClientFactory httpClientFactory,
        IEmbeddingService embeddingService,
        ILogger<XunfeiChatService> logger)
    {
        _context = context;
        _config = config.Value;
        _httpClientFactory = httpClientFactory;
        _embeddingService = embeddingService;
        _logger = logger;
    }

    public async Task<ChatResponseDto> GetAnswerAsync(ChatRequestDto request)
    {
        // 获取或创建对话
        var conversationId = request.ConversationId ?? Guid.NewGuid();
        var conversation = await _context.Conversations
            .Include(c => c.Messages)
            .FirstOrDefaultAsync(c => c.Id == conversationId);

        if (conversation == null)
        {
            conversation = await CreateConversationAsync();
            conversationId = conversation.Id;
        }

        // 获取相关文档块
        var questionEmbedding = await _embeddingService.GenerateEmbeddingAsync(request.Question);
        var questionVector = new Vector(questionEmbedding);

        var relevantChunks = await _context.DocumentChunks
            .OrderBy(c => c.Embedding!.CosineDistance(questionVector))
            .Take(3)
            .Include(c => c.Document)
            .ToListAsync();

        // 构建提示词
        var prompt = BuildPrompt(request.Question, relevantChunks);

        // 获取历史对话
        var history = conversation.Messages
            .OrderBy(m => m.CreatedAt)
            .Select(m => new { role = m.Role, content = m.Content })
            .ToList();

        // 调用讯飞API获取回答
        var response = await GetChatResponseAsync(prompt, history.Cast<object>().ToList());

        // 保存对话记录
        var userMessage = new Message
        {
            Id = Guid.NewGuid(),
            ConversationId = conversationId,
            Role = "user",
            Content = request.Question,
            CreatedAt = DateTime.UtcNow
        };

        var assistantMessage = new Message
        {
            Id = Guid.NewGuid(),
            ConversationId = conversationId,
            Role = "assistant",
            Content = response,
            CreatedAt = DateTime.UtcNow
        };

        _context.Messages.AddRange(userMessage, assistantMessage);
        await _context.SaveChangesAsync();

        // 返回结果
        return new ChatResponseDto
        {
            Answer = response,
            ConversationId = conversationId,
            Sources = relevantChunks.Select(chunk => new SourceDto
            {
                Content = chunk.Content,
                Source = chunk.Document.Source,
                Similarity = 1.0 / (1.0 + chunk.Embedding!.CosineDistance(questionVector))
            }).ToList()
        };
    }

    public async Task<List<Message>> GetConversationHistoryAsync(Guid conversationId)
    {
        return await _context.Messages
            .Where(m => m.ConversationId == conversationId)
            .OrderBy(m => m.CreatedAt)
            .ToListAsync();
    }

    public async Task<Conversation> CreateConversationAsync()
    {
        var conversation = new Conversation
        {
            Id = Guid.NewGuid(),
            UserId = Guid.NewGuid(), // 临时用户ID，后续可以改为实际用户
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow
        };

        _context.Conversations.Add(conversation);
        await _context.SaveChangesAsync();

        return conversation;
    }

    private string BuildPrompt(string question, List<DocumentChunk> relevantChunks)
    {
        var sb = new StringBuilder();
        sb.AppendLine("基于以下参考信息回答问题。如果参考信息不足以回答问题，请说明无法回答。");
        sb.AppendLine("\n参考信息：");
        
        foreach (var chunk in relevantChunks)
        {
            sb.AppendLine($"- {chunk.Content}");
        }

        sb.AppendLine("\n问题：");
        sb.AppendLine(question);
        
        return sb.ToString();
    }

    private async Task<string> GetChatResponseAsync(string prompt, List<dynamic> history)
    {
        try
        {
            var client = _httpClientFactory.CreateClient();
            var date = DateTime.UtcNow.ToString("r");
            var host = _config.ApiDomain;
            var path = _config.ChatPath;

            var messages = new List<dynamic>();
            foreach (var msg in history.Take(10)) // 限制历史消息数量
            {
                messages.Add(new { role = msg.role, content = msg.content });
            }
            messages.Add(new { role = "user", content = prompt });

            var requestBody = new
            {
                header = new
                {
                    app_id = _config.AppId
                },
                parameter = new
                {
                    chat = new
                    {
                        domain = "general",
                        temperature = 0.7,
                        max_tokens = 2048
                    }
                },
                payload = new
                {
                    message = new
                    {
                        text = messages
                    }
                }
            };

            var jsonBody = JsonSerializer.Serialize(requestBody);
            var signature = GenerateSignature("POST", host, path, date, jsonBody);

            var request = new HttpRequestMessage(HttpMethod.Post, $"https://{host}{path}")
            {
                Content = new StringContent(jsonBody, Encoding.UTF8, "application/json")
            };

            request.Headers.Add("Host", host);
            request.Headers.Add("Date", date);
            request.Headers.Add("Authorization", signature);

            var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();

            var jsonResponse = await response.Content.ReadAsStringAsync();
            var responseObj = JsonSerializer.Deserialize<XunfeiChatResponse>(jsonResponse);

            if (responseObj?.Header?.Code != 0)
            {
                throw new Exception($"讯飞API返回错误：{responseObj?.Header?.Message}");
            }

            return responseObj?.Payload?.Text?.Content ?? "抱歉，我无法生成回答。";
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "调用讯飞聊天API时发生错误");
            throw;
        }
    }

    private string GenerateSignature(string method, string host, string path, string date, string body)
    {
        var stringToSign = $"{method}\n{host}\n{path}\n{date}\n{body}";
        var secretBytes = Encoding.UTF8.GetBytes(_config.ApiSecret);
        
        using var hmac = new HMACSHA256(secretBytes);
        var signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
        var signature = Convert.ToBase64String(signatureBytes);

        return $"api_key=\"{_config.ApiKey}\", algorithm=\"hmac-sha256\", headers=\"host date request-line\", signature=\"{signature}\"";
    }
}

public class XunfeiChatResponse
{
    public ResponseHeader? Header { get; set; }
    public ChatPayload? Payload { get; set; }

    public class ResponseHeader
    {
        public int Code { get; set; }
        public string? Message { get; set; }
        public string? Sid { get; set; }
    }

    public class ChatPayload
    {
        public ChatText? Text { get; set; }
    }

    public class ChatText
    {
        public string? Content { get; set; }
        public List<Dictionary<string, string>>? Choices { get; set; }
    }
} 